﻿using System;
using System.Collections.Generic;
using CI.Utility;
using CI.Services;
using CI.ViewModels.Interfaces;
using QuickGraph;
using System.Windows;
using GongSolutions.Wpf.DragDrop;
using CI.Models;
using CI.Models.Production;
using CI.ViewModels.Commerce;

namespace CI.ViewModels.Diagramming
{
    public abstract class DiagramViewModel : CIPresenterBase, IDiagramViewModel, IDropTarget
    {
        private BidirectionalGraph<object, IEdge<object>> _graph;
        private BidirectionalGraph<object, IEdge<object>> _unboundGraph;
        private Dictionary<object, object> _vertexMapping = new Dictionary<object, object>();
        private Dictionary<Link, IEdge<object>> _edgeMapping = new Dictionary<Link, IEdge<object>>();

        protected DiagramViewModel()
        {
            Graph = new BidirectionalGraph<object, IEdge<object>>();
            LayoutOptions = new DiagramLayoutOptionsViewModel("Layout Options");
            _unboundGraph = Graph;
            StartModel();
        }

        protected void WireModel()
        {
            Model.NodeAdded += Model_NodeAdded;
            Model.NodeRemoved += Model_NodeRemoved;
            Model.LinkAdded += Model_LinkAdded;
            Model.LinkRemoved += Model_LinkRemoved;
        }

        void Model_LinkRemoved(object sender, LinkEventArgs e)
        {
            throw new NotImplementedException();
        }

        void Model_LinkAdded(object sender, LinkEventArgs e)
        {
            var src = e.Link.FromNode;
            var dst = e.Link.ToNode;

            // get verices
            var srcVtx = _vertexMapping[src];
            var dstVtx = _vertexMapping[dst];

            var edge = new Edge<object>(srcVtx, dstVtx);

            _edgeMapping.Add(e.Link, edge);

            Graph.AddEdge(edge);
        }

        void Model_NodeRemoved(object sender, NodeEventArgs e)
        {
            var vtx = _vertexMapping[e.Node];

            Graph.RemoveVertex(vtx);
        }

        void Model_NodeAdded(object sender, NodeEventArgs e)
        {
            //TODO:Conjure up vertex view model and add to diagram!
            var node = e.Node;

            if (node is ICharacter) AddVertex(new CharacterVertexViewModel(node as ICharacter, this), node);
            else if (node is ICorporation) AddVertex(new CorporationVertexViewModel(node as ICorporation, this), node);
            else if (node is BuyItemsJob) AddVertex(new BuyItemsVertexViewModel(node as BuyItemsJob, this), node);
        }

        private void AddVertex(object vertex, object node)
        {
            _vertexMapping.Add(node, vertex);

            Graph.AddVertex(vertex);
        }

        public BidirectionalGraph<object, IEdge<object>> Graph
        {
            get { return _graph; }
            private set { SetField(ref _graph, value, () => Graph); }
        }

        public DiagramLayoutOptionsViewModel LayoutOptions { get; private set; }

        public IDiagramModel Model { get; protected set; }

        public override void Initialize()
        {
            _unboundGraph = new BidirectionalGraph<object, IEdge<object>>();
            RebindGraph();
        }

        private void RebindGraph()
        {
            Graph = _unboundGraph;
        }

        public override bool CanShutdown()
        {
            return true;
        }

        public override void Shutdown()
        {
            //UnbindGraph();
        }

        public override void Activate()
        {
            //RebindGraph();
        }

        public override void Deactivate()
        {
            //UnbindGraph();
        }

        private void UnbindGraph()
        {
            Graph = null;
        }

        #region IDropTarget Members

        public abstract void DragOver(IDropInfo dropInfo);
        public abstract void Drop(IDropInfo dropInfo);

        #endregion
    }
}